package de.unidue.masterproject.plugin;

import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.JInternalFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;

import de.unidue.masterproject.plugin.classes_literaturplugin.Article;
import de.unidue.masterproject.plugin.classes_literaturplugin.ArticleQuote;
import de.unidue.masterproject.plugin.classes_literaturplugin.Book;
import de.unidue.masterproject.plugin.classes_literaturplugin.BookQuote;
import de.unidue.masterproject.plugin.classes_literaturplugin.Literature;
import de.unidue.masterproject.plugin.classes_literaturplugin.Quote;
import de.unidue.masterproject.plugin.classes_literaturplugin.Website;
import de.unidue.masterproject.plugin.classes_literaturplugin.WebsiteQuote;

public class JTreeContainer {

	private JTree tree;
	private DefaultMutableTreeNode root, articles, books, websites;
	
	private DefaultTreeModel model;
	
	private ArrayList<Literature> literatureList = new ArrayList<Literature>();
	private ArrayList<Quote> quoteList = new ArrayList<Quote>();
	private ArrayList<DefaultMutableTreeNode> nodeList = new ArrayList<DefaultMutableTreeNode>();
	
	private DisplayArea displayArea;
	
	public void initiateTree(){
		root.removeAllChildren();
		
		tree.setRootVisible(false);
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		
		tree.addTreeSelectionListener(
				new TreeSelectionListener() {
					@Override
					public void valueChanged(TreeSelectionEvent event) {
						TreePath path = tree.getSelectionPath();
						
						if(path == null){
							return;
						}
						
						DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)path.getLastPathComponent();
						Object o = selectedNode.getUserObject();
						System.out.println("Auswahl erfolgt");
						System.out.println(o);
						displayArea.show(o);
						
					}
				}
				);
		
		articles = new DefaultMutableTreeNode("Articles");		
		books = new DefaultMutableTreeNode("Books");
		websites = new DefaultMutableTreeNode("Websites");
		
		model.insertNodeInto(articles, root, root.getChildCount());
		model.insertNodeInto(books, root, root.getChildCount());
		model.insertNodeInto(websites, root, root.getChildCount());
		
		makePathVisibleTo(articles);
		
		DefaultMutableTreeNode tempNode;
				
		for(int i = 0; i<literatureList.size();i++){
			Literature l = literatureList.get(i);
			
			if(l instanceof Book){
				tempNode = new DefaultMutableTreeNode(l);
				model.insertNodeInto(tempNode, books, books.getChildCount());
				nodeList.add(tempNode);
			}
			else if(l instanceof Article){
				tempNode = new DefaultMutableTreeNode(l);
				model.insertNodeInto(tempNode, articles, articles.getChildCount());
				nodeList.add(tempNode);
			}
			else if(l instanceof Website){
				tempNode = new DefaultMutableTreeNode(l);
				model.insertNodeInto(tempNode, websites, websites.getChildCount());
				nodeList.add(tempNode);
			}
		}
		
		for(int i = 0; i<quoteList.size();i++){
			Quote q = quoteList.get(i);
			
			for(int j = 0; j<nodeList.size();j++){
				tempNode = nodeList.get(j);
				
				if(q.getReference() == (Literature)tempNode.getUserObject()){
					DefaultMutableTreeNode quoteNode = new DefaultMutableTreeNode(q);
					
					model.insertNodeInto(quoteNode, tempNode, tempNode.getChildCount());
				}
			}
		}
		
		tree.updateUI();	
	}
	
	private void makePathVisibleTo(DefaultMutableTreeNode node){
		TreeNode[] nodes = model.getPathToRoot(node);
		TreePath path = new TreePath(nodes);
		tree.makeVisible(path);
	}

	public Article createNewArticle(String author, int year, String title, String comment, String magazine, String pages){
		Article a = new Article(author, year, title, comment, magazine, pages);
		literatureList.add(a);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(a);
		model.insertNodeInto(temp, articles, articles.getChildCount());
		return a;
	}
	
	public Article createNewArticle(Article a){
		literatureList.add(a);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(a);
		model.insertNodeInto(temp, articles, articles.getChildCount());
		return a;
	}
	
	public Article changeExistingArticle(Article oldArticle, String author, int year, String title, String comment, String magazine, String pages){
		boolean succes = literatureList.contains(oldArticle);
		
		if(!succes){
			return null;
		}
		
		oldArticle.setAuthor(author);
		oldArticle.setComment(comment);
		oldArticle.setTitle(title);
		oldArticle.setYear(year);
		oldArticle.setMagazine(magazine);
		oldArticle.setPages(pages);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldArticle);
		model.nodeChanged(nodeToBeChanged);
		
		return oldArticle;
		
	}
	
	public Book createNewBook(String author, int year, String title, String comment, int edition, String town){
		Book b = new Book(author, year, title, comment, edition, town);
		literatureList.add(b);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(b);
		model.insertNodeInto(temp, books, books.getChildCount());
		return b;
	}
	
	public Book createNewBook(Book b){
		literatureList.add(b);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(b);
		model.insertNodeInto(temp, books, books.getChildCount());
		return b;
	}
	
	public Book changeExistingBook(Book oldBook, String author, int year, String title, String comment, int edition, String town){
		boolean succes = literatureList.contains(oldBook);
		
		if(!succes){
			return null;
		}
		
		oldBook.setAuthor(author);
		oldBook.setComment(comment);
		oldBook.setTitle(title);
		oldBook.setYear(year);
		oldBook.setEdition(edition);
		oldBook.setTown(town);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldBook);
		model.nodeChanged(nodeToBeChanged);
		
		return oldBook;
		
	}
	
	public Website createNewWebsite(String author, int year, String title, String comment, String url, String date){
		Website w = new Website(author, year, title, comment, url, date);
		literatureList.add(w);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(w);
		model.insertNodeInto(temp, websites, websites.getChildCount());
		return w;
	}
		
	public Website createNewWebsite(Website w){
		literatureList.add(w);
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(w);
		model.insertNodeInto(temp, websites, websites.getChildCount());
		return w;
	}
	
	public Website changeExistingWebsite(Website oldWebsite, String author, int year, String title, String comment, String url, String date){
		boolean succes = literatureList.contains(oldWebsite);
		
		if(!succes){
			return null;
		}
		
		oldWebsite.setAuthor(author);
		oldWebsite.setComment(comment);
		oldWebsite.setTitle(title);
		oldWebsite.setYear(year);
		oldWebsite.setUrl(url);
		oldWebsite.setDate(date);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldWebsite);
		model.nodeChanged(nodeToBeChanged);
		
		return oldWebsite;
		
	}
		
	public void createNewArticleQuote(Article reference, String content, String comment, String owner, boolean published, String pages){
		DefaultMutableTreeNode article = findNodeWithContent(reference);
		if(reference == null || article == null){
			return;
		}
		ArticleQuote aQ = new ArticleQuote(reference, content, comment, owner, published, pages);
		quoteList.add(aQ);
		
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(aQ);
		model.insertNodeInto(temp, article, article.getChildCount());
		
	}
	
	public ArticleQuote changeExistingArticleQuote(ArticleQuote oldArticleQuote, String content, String comment, String owner, boolean published, String pages){
		boolean succes = quoteList.contains(oldArticleQuote);
		
		if(!succes){
			return null;
		}
		
		oldArticleQuote.setContent(content);
		oldArticleQuote.setComment(comment);
		oldArticleQuote.setOwner(owner);
		oldArticleQuote.setPublished(published);
		oldArticleQuote.setPages(pages);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldArticleQuote);
		model.nodeChanged(nodeToBeChanged);
		
		return oldArticleQuote;	
	}
	
	public void createNewBookQuote(Book reference, String content, String comment, String owner, boolean published, String pages){
		DefaultMutableTreeNode book = findNodeWithContent(reference);
		
		if(reference == null || book == null){
			return;
		}
		
		BookQuote bQ = new BookQuote(reference, content, comment, owner, published, pages);
		quoteList.add(bQ);
		
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(bQ);
		model.insertNodeInto(temp, book, book.getChildCount());
	}
	
	public BookQuote changeExistingBookQuote(BookQuote oldBookQuote, String content, String comment, String owner, boolean published, String pages){
		boolean succes = quoteList.contains(oldBookQuote);
		
		if(!succes){
			return null;
		}
		
		oldBookQuote.setContent(content);
		oldBookQuote.setComment(comment);
		oldBookQuote.setOwner(owner);
		oldBookQuote.setPublished(published);
		oldBookQuote.setPages(pages);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldBookQuote);
		model.nodeChanged(nodeToBeChanged);
		
		return oldBookQuote;	
	}
	
	public void createNewWebsiteQuote(Website reference, String content, String comment, String owner, boolean published){
		DefaultMutableTreeNode website = findNodeWithContent(reference);
		
		if(reference == null || website == null){
			return;
		}
		
		WebsiteQuote wQ = new WebsiteQuote(reference, content, comment, owner, published);
		quoteList.add(wQ);
		
		DefaultMutableTreeNode temp = new DefaultMutableTreeNode(wQ);
		model.insertNodeInto(temp, website, website.getChildCount());
	}
	
	public WebsiteQuote changeExistingWebsiteQuote(WebsiteQuote oldWebsiteQuote, String content, String comment, String owner, boolean published){
		boolean succes = quoteList.contains(oldWebsiteQuote);
		
		if(!succes){
			return null;
		}
		
		oldWebsiteQuote.setContent(content);
		oldWebsiteQuote.setComment(comment);
		oldWebsiteQuote.setOwner(owner);
		oldWebsiteQuote.setPublished(published);
		
		DefaultMutableTreeNode nodeToBeChanged = findNodeWithContent(oldWebsiteQuote);
		model.nodeChanged(nodeToBeChanged);
		
		return oldWebsiteQuote;	
	}
	
	public void remove(){
		DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
		
		
		if((selectedNode == root) || (selectedNode == articles) ||
				(selectedNode == books) || (selectedNode == websites)){
			return;
		}
		
		
		if(selectedNode.getUserObject() instanceof Quote){
			Quote q = (Quote)selectedNode.getUserObject();
			quoteList.remove(q);
			model.removeNodeFromParent(selectedNode);
		}
		else if(selectedNode.getUserObject() instanceof Literature){
			if(selectedNode.isLeaf()){
				Literature l = (Literature)selectedNode.getUserObject();
				literatureList.remove(l);
				model.removeNodeFromParent(selectedNode);
			}
			else{	
				for (@SuppressWarnings("unchecked")
				Enumeration<DefaultMutableTreeNode> e = selectedNode.children(); e.hasMoreElements();){	
					Quote q = (Quote)e.nextElement().getUserObject();
					quoteList.remove(q);
				}
				
				Literature l = (Literature)selectedNode.getUserObject();
				literatureList.remove(l);
				model.removeNodeFromParent(selectedNode);
			}
		}
		
	}

	public JTreeContainer(int x, int y,  int width, int height, JInternalFrame frame, DisplayArea displayArea){
		root = new DefaultMutableTreeNode("Available Literature");
		model = new DefaultTreeModel(root);
		tree = new JTree(model);
		
		JScrollPane scrollPane = new JScrollPane(tree);
		scrollPane.setBounds(x, y, width, height);
		
		//tree.setBounds(x, y, width, height);
		//frame.add(tree);
		frame.add(scrollPane);
		this.displayArea = displayArea;
		
		initiateTree();
	}

	private DefaultMutableTreeNode findNodeWithContent(Object content){
		for (@SuppressWarnings("unchecked")
		Enumeration<DefaultMutableTreeNode> e = root.breadthFirstEnumeration(); e.hasMoreElements();){	
			DefaultMutableTreeNode d = e.nextElement();
			Object o = d.getUserObject();
			if(content == o){
				return d;
			}
		}
		return null;
	}

	public Literature getSelectedLiterature(){
		DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
		
		if(selectedNode == null || selectedNode == root || selectedNode == articles || selectedNode == books || selectedNode == websites){
			return null;
		}
		
		if(selectedNode.getUserObject() instanceof Literature){
			return (Literature)selectedNode.getUserObject();
		}
		else{
			return (Literature)((DefaultMutableTreeNode)selectedNode.getParent()).getUserObject();
		}
		
	}

	public Object getSelectedNode(){
		DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
		
		if(selectedNode == null || selectedNode == root || selectedNode == articles || selectedNode == books || selectedNode == websites){
			return null;
		}
		
		return selectedNode.getUserObject();	
	}
	
	public int getNumberOfLiterature(){
		return literatureList.size();
	}
	
	public int getNumberOfQuotes(){
		return quoteList.size();
	}

	/**
	 * @return the literatureList
	 */
	public ArrayList<Literature> getLiteratureList() {
		return literatureList;
	}

	/**
	 * @return the quoteList
	 */
	public ArrayList<Quote> getQuoteList() {
		return quoteList;
	}
}
